Cloud Logging
ログの送信
Incoming log entries must have timestamps that don't exceed the logs retention period in the past, and that don't exceed 24 hours in the future. Log entries outside those time boundaries aren't ingested by Logging.
書き込むログの timestamp は 保持期間~将来24h の間の時刻でないと取り込まれない
jsonPayload の中の値で上書きできる
時刻関連フィールド、個人的には time を使う
読みやすい
フィールドが1つ
Logging 経由でないログを BigQuery に入れる際にそのまま --time_partitioning_field に渡せる
場合によってはフォーマット分遅い
GAE や GKE 内での挙動やオプションはプラグイン見ると雰囲気分かるかも fluetnd 設定
Sink の設定
sync ではなく sink、エクスポート設定のこと
予め設定しておく必要ある
sink は、作成した後に書かれたログを振り分ける仕組み
gcloud logging read {FILTER} でクエリして、それを BigQuery なりに入れるかんたんな方法
時間や IO コストはかかる
アプリケーションログは、予め取り敢えず GCS に置いておくと良さそう Cloud Storage への sink
バケットを指定して保存する
複数のエクスポート設定を同じバケットへ向けられるので logName ごとに設定したり(細かい) resource.type="gae_app" など同じ構造が期待される汎用のフィールドで作ったりしている
ログデータの logName(lodId) フィールドからディレクトリ構造が決まる
"logName": "projects/adtrust/logs/stdout" (logId は stdout)
gs://{bucket}/stdout/yyyy/mm/dd/00:00:00_00:59:59_S0.json
bucket 下に
decodeURIComponent(logId) されたディレクトリが作られ
日付ディレクトリが yyyy/mm/dd/ が掘られ
1時間ごとの NDJSON が書かれる(流量によって S0部分は増えて分割されそう)
"logName":"projects/adtrust/logs/%2Fvar%2Flog%2Fnginx%2Ferror.log" のような logName は gs://{bucket}/var/log/nginx/error.log/yyyy/mm/dd/... にデコードされた名前になる
ログの時刻と到着した時刻の書かれる先
ここにめっちゃかいてある
ファイル単位のシャードは 60分ウィンドウ
S0, S1 のようなシャード suffix
A1, A2 のような追加(Additional)のシャード suffix
こちらは書かれた UnixTimestamp が後ろに付く
timestamp と receiveTimestamp が同じウィンドウに入るなら S、別なら A
A も timestamp の時刻を 60分ウィンドウにしたものがファイル名
ログエントリが 08:50:00 の timestamp と、09:10:00 の receiveTimestamp を持ち、2021 年 3 月 25 日の 09:15:00 にエクスポートされた場合、付録ファイルには次のように書き込まれます。
08:00:00_08:59:59_A0.json:1616681700
{timestamp window}_A{index}.json:{exported time}
exported time は観測した範囲では15分おき
実際 59-00 分前後のアクセスログなんかは timestamp と receivedTimestamp が大抵ウィンドウをまたぐので、よく A のファイルは作成される
ログの意味に従って timestamp をつけるべき
BigQuery への sink
WriterIdentity
最近は sink 作成時にユニークなサービスアカウントが作成される
現行: [GENERATED_ID_1]@[GENERATED_ID_2].iam.gserviceaccount.com
GENERATED_ID_2 って常に gcp-sa-loggingじゃないの?
以前: cloud-logs@system.gserviceaccount.com
現行のものはこのサービスアカウントに権限を付与してあげないといけない
table:roles
Cloud Storage roles/storage.objectCreator
BigQuery roles/bigquery.dataEditor
Cloud Pub/Sub roles/pubsub.publisher
Logging Bucket roles/logging.bucketWriter
書き込みID は witer identity のこと
Terraform では
google_logging_project_sink.{name}.writer_identity で serviceAccount:... の文字列が取れる
ログフィールドの型
jsonPayload 内部にあるログフィールドの型は、ログエントリの受信時にフィールドの値から推測されます。
値が引用符なしの数値であるフィールドの型は double です。
大きい数値などは指数表記になったりもする
普通に整数をログに書いたとして、double の仮数部が整数の精度の限界になるか(53bit)?
高度なログフィルタ
比較演算子
= は一致、 : 含む
= # equal
: # "has" matches any substring in the log entry field
timestamp
timestamp > "2019-11-11T21:06:00+09:00" のように timezone をかける
RFC 3339 形式の文字列。たとえば 2014-10-02T15:01:23.045Z です。フィルタ式では、タイムスタンプに Z または ±hh:mm でタイムゾーンを指定することができます。タイムスタンプは、ナノ秒単位の精度で表されます。
よく使うフィルタ
log_id("stdout") OR log_id("stderr")
標準出力または標準エラー出力
resource.type = "gae_app" や "cloud_function"
httpRequest.requestUrl = "/..."
httpRequest.status >= 500
httpRequest.latency >= ...
-httpRequest:*
httpRequest フィールドに何か持つログを除く除外条件
timestamp
severity >= WARNING
大小比較できる
基本モードでは一定以上のログレベルをフィルタする UI だけど高度なフィルタなら = で選択できる
trace
クリックすると "一致エントリを表示" で同じトレースのログを表示できる
-resource.labels.namespace_name="kube-system"
GKE の kube-system のログを除く
-resource.type="http_load_balancer" AND protoPayload.latency >= "300ms"
LB 除いた backend service (AppEngine) で 300ms 以上かかったリクエスト
sample
サンプリングのための sample 関数が提供されている
sample(field, fraction)
field でハッシュ化した値を fraction の割合でサンプリングする
sample(insertId, 0.01) なら insertId はログごとにユニークなため全体を 1% サンプリング
trace でフィルタするとtrace 単位でサンプリングするので、同じ trace のログはすべて含めることができる
フィルタ
field:* で field があることを表す field-exists、-httpRequest:* で除外できる
index 貼られているフィールド
オブジェクトの配列
jsonPayload.items.name="foo" は items 以下のオブジェクトの name のうち1つが "foo" ならマッチする
("jsonPayload": { "items": [ { "name": ... }, { "name": ... }, ... ] } みたいな構造のとき)
log_id
logName="projects/{PROJECT_ID}/logs/{LOG_ID}" の、LOG_ID 部分でクエリできる
たとえば log_id("requests") で、Cloud Load Balancing や GAE のアクセスログ
CLI
gcloud logging read {FILTER} で取れる
よく使うオプション
--project: プロジェクトは大抵指定したい
--limit=1000: ログエントリの数
デフォルトは unlimited と書いてあるがほんとか?
--order=desc|asc timestamp に対して指定する
--freshness=3d: 直近の期間をかんたんに指定できる
timestamp フィルタの範囲が freshness に含まれている必要があるかどうか → なさそう
timestamp を満たすように読む範囲をよしなにしていそう?
freshness とかぶらない範囲で指定しても timestamp の範囲のログが取得される
--format=json: json なら jq に pipe して見やすく色がつくしフィルタつけれる GAE のトラフィック割合ここにも出る
マジ気が利いていて偉い
https://gyazo.com/df39cc00b516239beecea4c7ee9c4815